package com.fujimana.rockincat.restree.init;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

public class URLScanner implements Scanner {

	private Set<String> result;

	public URLScanner() {
		this.result = new HashSet<String>();
	}

	@Override
	public Set<String> getResult() {
		return Collections.unmodifiableSet(this.result);
	}

	@Override
	public void scanDirectory(File directory) {
		handleDirectory(directory, null);
	}

	private void handleDirectory(File file, String path) {
		for (File child : file.listFiles()) {
			String newPath = path == null ? child.getName() : path + '/'
					+ child.getName();
			if (child.isDirectory()) {
				handleDirectory(child, newPath);
			} else {
				this.result.add(child.getPath());
			}
		}
	}

	@Override
	public void scanResource(String resource) {
		Set<String> paths = new HashSet<String>();

		try {
			Enumeration<URL> urlEnum = Thread.currentThread()
					.getContextClassLoader().getResources(resource);

			while (urlEnum.hasMoreElements()) {

				String urlPath = urlEnum.nextElement().getFile();
				urlPath = URLDecoder.decode(urlPath, "UTF-8");

				if (urlPath.startsWith("file:")) {
					urlPath = urlPath.substring("file:".length());
				}

				if (urlPath.indexOf('!') > 0) {
					urlPath = urlPath.substring(0, urlPath.indexOf('!'));
				} else {
					File dirOrArchive = new File(urlPath);
					urlPath = dirOrArchive.getParent();
				}
				paths.add(urlPath);
			}
		} catch (IOException e) {
			// TODO
		}

		handle(paths);
	}

	private void handle(Set<String> paths) {
		for (String urlPath : paths) {
			try {
				File file = new File(urlPath);
				if (file.isDirectory()) {
					handleDirectory(file, null);
				} else {
					handleArchiveByFile(file);
				}
			} catch (IOException ioe) {
				// TODO
			}
		}
	}

	private void handleArchiveByFile(File file) throws IOException {
		try {
			ZipFile zip = new ZipFile(file);
			Enumeration<? extends ZipEntry> entries = zip.entries();
			while (entries.hasMoreElements()) {
				ZipEntry entry = entries.nextElement();
				String name = entry.getName();
				this.result.add(name);
			}
		} catch (ZipException e) {
			// TODO
		}
	}
}
